package org.springblade.modules.auth.utils;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.common.config.ScheduleTask;
import org.springblade.modules.desk.vo.AlertsVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.util.StringUtils;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * 消息通知
 * 微信
 * 钉钉
 * 短信
 * 邮件
 * 语音电话
 *
 * @author zxf
 */
@Configuration
@EnableAsync
public class NoticeAlertUtil {

	/**
	 * 阿里云配置
	 */
	@Value("${spring.aliyun.accessKeyId}")
	private String aliyunAccessKeyId;
	@Value("${spring.aliyun.secret}")
	private String aliyunSecret;

	@Value("${spring.mail.username}")
	private String sendFrom;

	@Autowired
	private JavaMailSenderImpl javaMailSender;
	@Autowired
	private TemplateEngine templateEngine;

	private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleTask.class);

	@Async
	public String weixinAlert(AlertsVO tempAlert, Long serial,Map<String, String> params) {
		LOGGER.info("发送微信通知：" + params.get("weixin.corpid") + params.get("weixin.corpsecret"));
		Map map = new HashMap<>();
		map.put("corpid", params.get("weixin.corpid"));
		map.put("corpsecret", params.get("weixin.corpsecret"));
		//链式构建请求
		String tokenStr = HttpRequest.get(params.get("weixin.tokenurl")).form(map)
			//超时，毫秒
			.timeout(20000)
			.execute().body();

		JSONObject tokenJSON = JSON.parseObject(tokenStr);
		if (tokenJSON.getInteger("errcode") == 0) {
			LOGGER.info("获取微信token成功");
			//发送消息内容
			Map sendContent = new HashMap();
			sendContent.put("touser", "@all");
			sendContent.put("toparty", "@all");
			sendContent.put("totag", "@all");
			sendContent.put("msgtype", "text");
			sendContent.put("agentid", Integer.valueOf(params.get("weixin.agentid")));
			Map textContent = new HashMap();
			JSONObject message =  transferMessage(tempAlert.getMessage());
			String content = "告警主机: " + message.get("hostName") + "\n\n" +
				"设备IP: " + message.get("hostIP") + "\n\n" +
				"告警等级: " + transferSeverity(message.get("eventSeverity").toString()) + "\n\n" +
				"问题概述: " + message.get("eventName") + "\n\n";

			if(tempAlert.getPEventid()==null){
				content += "告警时间: " + transferDateTime(message.get("eventTime").toString()) + "\n\n";
			}else {
				content = "故障已修复" + "\n\n"+content;
				content += "修复时间: " + transferDateTime(message.get("eventTime").toString()) + "\n\n";
			}

			textContent.put("content", content);
			sendContent.put("text", textContent);
			sendContent.put("safe", 0);
			sendContent.put("enable_id_trans", 0);
			sendContent.put("enable_duplicate_check", 0);
			sendContent.put("duplicate_check_interval", 0);

			String sendContentResultStr = HttpRequest.post(params.get("weixin.sendurl") + "?access_token=" + tokenJSON.get("access_token"))
				.body(JSON.toJSONString(sendContent))
				//超时，毫秒
				.timeout(20000)
				.execute().body();
			JSONObject sendContentResultJSON = JSON.parseObject(sendContentResultStr);
			if (sendContentResultJSON.getInteger("errcode") == 0) {
				LOGGER.info("微信告警信息发送成功：" + JSON.toJSONString(sendContent));
			} else {
				LOGGER.error("微信告警信息发送失败，请联系管理员");
			}

		} else {
			LOGGER.error("获取微信token失败，请联系管理员");
		}
		return null;
	}

	@Async
	public String dingdingAlert(AlertsVO tempAlert, Long serial,Map<String, String> params) {
		LOGGER.info("发送钉钉通知：" + params.get("dingding.sendurl"));
		//发送消息内容
		Map sendContent = new HashMap();
		Map textContent = new HashMap();
		JSONObject message =  transferMessage(tempAlert.getMessage());
		String content = "告警主机: " + message.get("hostName") + "\n\n" +
			"设备IP: " + message.get("hostIP") + "\n\n" +
			"告警等级: " + transferSeverity(message.get("eventSeverity").toString()) + "\n\n" +
			"问题概述: " + message.get("eventName") + "\n\n";

		if(tempAlert.getPEventid()==null){
			content += "告警时间: " + transferDateTime(message.get("eventTime").toString()) + "\n\n";
		}else {
			content = "故障已修复" + "\n\n"+content;
			content += "修复时间: " + transferDateTime(message.get("eventTime").toString()) + "\n\n";
		}

		textContent.put("content", content);
		sendContent.put("text", textContent);
		sendContent.put("msgtype", "text");

		String sendContentResultStr = HttpRequest.post(params.get("dingding.sendurl"))
			.body(JSON.toJSONString(sendContent))
			//超时，毫秒
			.timeout(20000)
			.execute().body();
		JSONObject sendContentResultJSON = JSON.parseObject(sendContentResultStr);
		if (sendContentResultJSON.getInteger("errcode") == 0) {
			LOGGER.info("钉钉告警信息发送成功：" + JSON.toJSONString(sendContent));
		} else {
			LOGGER.error("钉钉告警信息发送失败，请联系管理员");
		}
		return null;
	}

	/**
	 * 邮件通知
	 *
	 * @param tempAlert
	 * @param serial
	 * @return
	 */
	@Async
	public String emailAlert(AlertsVO tempAlert, Long serial,Map<String, String> params) {
		try {
			JSONObject message = transferMessage(tempAlert.getMessage());
			message.put("eventSeverity", transferSeverity(message.getString("eventSeverity")));
			message.put("eventTime", transferDateTime(message.get("eventTime").toString()));
			//读取模板
			Context context = new Context();
			context.setVariable("tempAlert", message);
			String mailTemplate = null;
			MimeMessage mimeMessage = javaMailSender.createMimeMessage();
			MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
			helper.setFrom(sendFrom);
			helper.setTo(params.get("emailTo"));

			if(tempAlert.getPEventid()==null){
				helper.setSubject(params.get("emailSubject"));
				mailTemplate = templateEngine.process("mailTemplate", context);
			}else {
				helper.setSubject("故障已修复");
				mailTemplate = templateEngine.process("mailTemplateResolved", context);
			}
			if(!StringUtils.isEmpty(params.get("emailCc"))){
				String[] emailCcs = params.get("emailCc").split(",");
				helper.setCc(emailCcs);
			}
			helper.setText(mailTemplate, true);
			javaMailSender.send(mimeMessage);
		} catch (MessagingException e) {
			LOGGER.error("邮件告警信息发送失败，请联系管理员");
		}

		LOGGER.info("邮件告警信息发送成功");
		return "success";
	}

	/**
	 * 短信通知
	 *
	 * @param tempAlert
	 * @param serial
	 * @return
	 */

	@Async
	public String messageAlert(AlertsVO tempAlert, Long serial,Map<String, String> params) {
		LOGGER.info("发送短信通知：");
		DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", aliyunAccessKeyId, aliyunSecret);
		IAcsClient client = new DefaultAcsClient(profile);

		CommonRequest request = new CommonRequest();
		request.setSysMethod(MethodType.POST);
		request.setSysDomain(params.get("aliyun.message.sysDomain"));
		request.setSysVersion(params.get("aliyun.message.sysVersion"));
		request.setSysAction(params.get("aliyun.message.sysAction"));
		request.putQueryParameter("RegionId", params.get("aliyun.message.regionId"));
		request.putQueryParameter("PhoneNumbers", params.get("aliyun.message.PhoneNumbers"));
		request.putQueryParameter("SignName", params.get("aliyun.message.signName"));
		request.putQueryParameter("TemplateCode", params.get("aliyun.message.templateCode"));
		Map templateParam = new HashMap();
		JSONObject message =  transferMessage(tempAlert.getMessage());

		templateParam.put("hostName", transferIP(message.get("hostName").toString()));
		templateParam.put("hostAddress", transferIP(message.get("hostIP").toString()));
		templateParam.put("eventSeverity", transferSeverity(message.get("eventSeverity").toString()));
		templateParam.put("eventName", "见邮件或群消息");
		templateParam.put("eventTime", transferDateTime(message.get("eventTime").toString()));

		request.putQueryParameter("TemplateParam", JSON.toJSONString(templateParam));
		try {
			CommonResponse response = client.getCommonResponse(request);
			System.out.println(response.getData());
			JSONObject sendContentResultJSON = JSON.parseObject(response.getData());
			if ("OK".equals(sendContentResultJSON.getString("Code"))) {
				LOGGER.info("短信告警信息发送成功：" + JSON.toJSONString(sendContentResultJSON));
			} else {
				LOGGER.error("短信告警信息发送失败，请联系管理员");
			}
		} catch (ServerException e) {
			e.printStackTrace();
		} catch (ClientException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 语音电话通知
	 *
	 * @param tempAlert
	 * @param serial
	 * @return
	 */
	@Async
	public String phoneCallAlert(AlertsVO tempAlert, Long serial,Map<String, String> params) {
		JSONObject message =  transferMessage(tempAlert.getMessage());

		DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", aliyunAccessKeyId, aliyunSecret);
		IAcsClient client = new DefaultAcsClient(profile);

		CommonRequest request = new CommonRequest();
		request.setSysMethod(MethodType.POST);
		request.setSysDomain(params.get("aliyun.phone.sysDomain"));
		request.setSysVersion(params.get("aliyun.phone.sysVersion"));
		request.setSysAction(params.get("aliyun.phone.sysAction"));
		request.putQueryParameter("RegionId", params.get("aliyun.phone.regionId"));
		request.putQueryParameter("CalledShowNumber", params.get("aliyun.phone.calledShowNumber"));

		request.putQueryParameter("CalledNumber", params.get("aliyun.phone.CalledNumber"));

		//TODO 后续扩展多语音

		request.putQueryParameter("TtsCode", params.get("aliyun.phone.ttsCode"));
		Map templateParam = new HashMap();
		templateParam.put("hostname", transferIP(message.get("hostName").toString()));
		templateParam.put("severity", transferSeverity(message.get("eventSeverity").toString()));
		templateParam.put("subject", "见群信息或邮件");
		templateParam.put("eventTime", transferDateTime(message.get("eventTime").toString()));
		request.putQueryParameter("TtsParam", JSON.toJSONString(templateParam));
		request.putQueryParameter("PlayTimes", params.get("aliyun.phone.playTimes"));
		try {
			CommonResponse response = client.getCommonResponse(request);
			System.out.println(response.getData());
			JSONObject sendContentResultJSON = JSON.parseObject(response.getData());
			if ("OK".equals(sendContentResultJSON.getString("Code"))) {
				LOGGER.info("语音告警信息发送成功：" + JSON.toJSONString(sendContentResultJSON));
			} else {
				LOGGER.error("语音告警信息发送失败，请联系管理员");
			}
		} catch (ServerException e) {
			e.printStackTrace();
		} catch (ClientException e) {
			e.printStackTrace();
		}
		return null;
	}


	public static JSONObject transferMessage(String message){
		JSONObject json = new JSONObject();
		String[] split = message.replaceAll("\\n","").split("\\|\\|\\|");
		for (String temp : split) {
			String[] splitKeyValues = temp.trim().split(":::");
			json.put(splitKeyValues[0], splitKeyValues[1]);
		}
		return json;
	}

	public String transferIP(String ip){

		return ip.replaceAll("\\.", "-");
	}


	public static String transferDateTime(String date){
		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss");
		return LocalDateTime.parse(date,dateTimeFormatter).format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"));
	}

	public static String transferSeverity(String level){
		String des;
		switch (level){
			case "2":
				des = "警告";
				break;
			case "3":
				des = "一般严重";
				break;
			case "4":
				des = "严重";
				break;
			case "5":
				des = "灾难";
				break;
			default:
				des = "信息";
		}
		return des;
	}

}
